
package ch.hearc.securiteSysteme.serie2.ex2ChallengeResponse.client.socket;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javax.swing.event.EventListenerList;

/**
 * 
 * @author Raphaël Capocasale
 *
 */
public class SocketClient implements Client_I
	{
	
	/*------------------------------------------------------------------*\
	|*							Attributs Private						*|
	\*------------------------------------------------------------------*/
	//input
	private String m_address;
	private int m_serverPort;
	
	//tools
	private Socket m_socket;
	
	private ObjectOutputStream m_outObject;
	private ObjectInputStream m_inObject;
	
	private Thread m_threadReception;
	private final EventListenerList m_listener = new EventListenerList();
	private boolean m_isConnected;
	
	/*------------------------------------------------------------------*\
	|*							Constructeurs							*|
	\*------------------------------------------------------------------*/
	public SocketClient()
		{
		m_isConnected = false;
		}
	
	/*------------------------------------------------------------------*\
	|*							Methodes Public							*|
	\*------------------------------------------------------------------*/
	@Override
	public void setAddress(String address)
		{
		m_address = address;
		}
	
	@Override
	public void setServerPort(int port)
		{
		m_serverPort = port;
		}
	
	@Override
	public void connect()
		{
		new Thread(new Runnable()
			{
				
				@Override
				public void run()
					{
					signalNotification("Connection...");
					if (!m_isConnected)
						{
						try
							{
							System.out.println("adresse: " + m_address + " port: " + m_serverPort);
							m_socket = new Socket(m_address, m_serverPort);
							
							m_isConnected = true;
							
							m_outObject = new ObjectOutputStream(m_socket.getOutputStream());
							m_inObject = new ObjectInputStream(m_socket.getInputStream());
							
							m_threadReception = new Thread(new Runnable()
								{
									
									@Override
									public void run()
										{
										Object obj = null;
										signalNotification("Connection established ! ");
										while(m_isConnected)
											{
											try
												{
												obj = (Object)m_inObject.readObject();
												if (obj != null)
													{
													signalMessageReceived(obj);
													}
												}
											catch (Exception e)
												{
												actionConnectionProblem();
												break;
												}
											}
										}
								});
							
							m_threadReception.start();
							}
						catch (IOException e)
							{
							actionConnectionProblem();
							}
						}
					else
						{
						signalNotification("already connected !");
						}
					}
			}).start();
		
		}
	
	@Override
	public void disconnect() throws IOException
		{
		m_isConnected = false;
		if (m_outObject != null)
			{
			m_outObject.close();
			}
		
		if (m_inObject != null)
			{
			m_inObject.close();
			}
		
		if (m_socket != null)
			{
			m_socket.close();
			}
		
		if (m_threadReception != null && m_threadReception.isAlive())
			{
			m_threadReception.interrupt();
			}
		}
	
	@Override
	public void send(Object obj) throws IOException
		{
		m_outObject.writeObject(obj);
		m_outObject.flush();
		}
	
	@Override
	public void addClientListener(ClientListener_I listener)
		{
		m_listener.add(ClientListener_I.class, listener);
		}
	
	@Override
	public void removeClientListener(ClientListener_I listener)
		{
		m_listener.remove(ClientListener_I.class, listener);
		}
	
	@Override
	public ClientListener_I[] getClientListeners()
		{
		return m_listener.getListeners(ClientListener_I.class);
		}
	
	/*------------------------------------------------------------------*\
	|*							Methodes Private						*|
	\*------------------------------------------------------------------*/
	protected void signalMessageReceived(Object obj)
		{
		for(ClientListener_I listener:this.getClientListeners())
			{
			listener.slotMessageReceived(obj);
			}
		}
	
	protected void signalNotification(String notification)
		{
		for(ClientListener_I listener:this.getClientListeners())
			{
			listener.slotNotification(notification);
			}
		}
	
	protected void signalConnectionLost(Client_I client)
		{
		for(ClientListener_I listener:this.getClientListeners())
			{
			listener.slotConnectionLost(client);
			}
		}
	
	private void actionConnectionProblem()
		{
		signalNotification("Connection problem !");
		m_isConnected = false;
		m_socket = null;
		signalConnectionLost(SocketClient.this);
		}
	
	@Override
	public void setClientPort(int port)
		{
		//rien		
		}
	
	}
